﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace BPMS.Utility.Converter
{
    public class TypeParser
    {
        /// <summary>
        /// 将IP转换为long型
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static long ToIPLong(object ip)
        {
            byte[] bytes = IPAddress.Parse(ToString(ip)).GetAddressBytes();
            return (long)bytes[3] + (((uint)bytes[2]) << 8) + (((uint)bytes[1]) << 16) + (((uint)bytes[0]) << 24);
        }

        /// <summary>
        /// 将Int64转换成IPAddress
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IPAddress ToIPAddress(Int64 source)
        {
            Byte[] b = new Byte[4];
            for (int i = 0; i < 4; i++)
                b[3 - i] = (Byte)(source >> 8 * i & 255);
            return (new IPAddress(b));
        }

        /// <summary>
        /// 字符串是否为DateTime类型
        /// </summary>
        /// <param name="dateString"></param>
        /// <returns></returns>
        public static bool IsDateTime(object dateObj)
        {
            if (dateObj == null || dateObj == DBNull.Value)
                return false;
            return IsDateTime(dateObj.ToString());
        }

        /// <summary>
        /// 将Dunull字段赋值转为时间
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(object time)
        {
            DateTime dt = DateTime.Parse("1900-1-1");
            if (time == null || DBNull.Value == time)
            {
                return dt;
            }
            if (IsDateTime(time))
            {
                dt = DateTime.Parse(time.ToString());
            }
            return dt;
        }
        /// <summary>
        /// 转换为字符串
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string ToString(object source)
        {
            if (null == source || DBNull.Value == source)
                return string.Empty;
            return source.ToString();
        }

        /// <summary>
        /// 转化为bool型
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool ToBoolean(object source)
        {
            bool reValue;
            bool.TryParse(ToString(source), out reValue);
            return reValue;
        }
        /// <summary>转化为Byte型</summary>
        public static Byte ToByte(object source)
        {
            Byte reValue;
            Byte.TryParse(ToString(source), out reValue);
            return reValue;
        }
        /// <summary> 转化为Short型</summary>
        public static short ToShort(object source)
        {
            short reValue;
            short.TryParse(ToString(source), out reValue);
            return reValue;
        }
        /// <summary>转化为Short型</summary>
        public static short ToInt16(object source)
        {
            short reValue;
            short.TryParse(ToString(source), out reValue);
            return reValue;
        }

        /// <summary>转化为int32型</summary>
        public static int ToInt32(object source)
        {
            int reValue;
            Int32.TryParse(ToString(source), out reValue);
            return reValue;
        }
        /// <summary>转化为int32型</summary>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static int ToInt32(object source, int defaultValue = 0)
        {
            int reValue;
            return Int32.TryParse(ToString(source), out reValue) ? reValue : defaultValue;
        }
        /// <summary>转化为int64型</summary>
        public static long ToInt64(object source)
        {
            long reValue;
            Int64.TryParse(ToString(source), out reValue);
            return reValue;
        }
        /// <summary>转化为Float型</summary>
        public static float ToFloat(object source)
        {
            float reValue;
            float.TryParse(ToString(source), out reValue);
            return reValue;
        }
        /// <summary>转化为Double型</summary>
        public static Double ToDouble(object source)
        {
            Double reValue;
            Double.TryParse(ToString(source), out reValue);
            return reValue;
        }
        /// <summary>转化为decimal型</summary>
        public static decimal ToDecimal(object source)
        {
            decimal reValue;
            decimal.TryParse(ToString(source), out reValue);
            return reValue;
        }
        /// <summary>转化为数字类型的日期</summary>
        public static decimal ToDateTimeDecimal(object source)
        {
            DateTime reValue;
            return DateTime.TryParse(ToString(source), out reValue) ? ToDecimal(reValue.ToString("yyyyMMddHHmmss")) : 0;
        }
        /// <summary>将时间转换成数字</summary>
        public static decimal ToDateTimeDecimal(DateTime source)
        {
            return ToDecimal(source.ToString("yyyyMMddHHmmss"));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static T ToObject<T>(object data)
        {
            Type targetType = GenericType<T>();
            if (null == data || data == DBNull.Value)
            {
                if (targetType == typeof(DateTime))
                {
                    //如果取日期类型的默认值 0001/01/01 ,在WCF JSON序列化的时候，会失败。
                    object o = new DateTime(1900, 1, 1);
                    return (T)o;
                }
                return default(T);
            }
            MethodInfo method = targetType.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static,
                Type.DefaultBinder, new[] { typeof(string), targetType.MakeByRefType() }, new[] { new ParameterModifier(2) });
            if (null != method)
            {
                var paramValue = new[] { data.ToString(), Activator.CreateInstance(targetType) };
                method.Invoke(null, paramValue);
                return (T)paramValue[1];
            }
            return (T)Convert.ChangeType(data, targetType);
        }

        public static T ConvertValue<T>(object value)
        {
            Type targetType = GenericType<T>();
            if (value == null || value == DBNull.Value)
            {
                if (targetType == typeof(DateTime))
                {
                    //如果取日期类型的默认值 0001/01/01 ,在WCF JSON序列化的时候，会失败。
                    object o = new DateTime(1900, 1, 1);
                    return (T)o;
                }
                return default(T);
            }
            if (targetType.IsEnum == true)
            {
                return (T)Enum.Parse(targetType, ConvertValue<System.String>(value), true);
            }
            switch (targetType.ToString())
            {
                case "System.Byte":
                case "System.SByte":
                case "System.Char":
                case "System.Decimal":
                case "System.Double":
                case "System.Single":
                case "System.Int32":
                case "System.UInt32":
                case "System.Int64":
                case "System.UInt64":
                case "System.Int16":
                case "System.UInt16":
                case "System.Guid":
                case "System.DateTime":
                case "System.String":
                    return (T)Convert.ChangeType(value, targetType);
                case "System.Boolean":
                    Boolean boolRetVal;
                    if (Boolean.TryParse(value.ToString(), out boolRetVal) == true)
                        return (T)(object)boolRetVal;
                    switch (value.ToString().ToUpper())
                    {
                        case "ON":
                        case "1":
                        case "YES":
                        case "TRUE": return (T)(object)true;
                        case "OFF":
                        case "0":
                        case "NO":
                        case "FALSE": return (T)(object)false;
                        default:
                            return default(T);
                    }
                case "System.Byte[]":
                    try
                    {
                        return (T)(object)value; //attempt simple cast
                    }
                    catch
                    {
                        BinaryFormatter bf = new BinaryFormatter();
                        using (MemoryStream ms = new MemoryStream())
                        {
                            bf.Serialize(ms, value);
                            ms.Seek(0, 0);
                            return (T)(object)ms.ToArray();
                        }
                    }
                default:
                    return default(T);
            }
        }

        public static Type GenericType<T>()
        {
            Type type = typeof(T);
            if (type.IsGenericType
                && typeof(Nullable<>).Equals(type.GetGenericTypeDefinition()))
            {
                type = type.GetGenericArguments()[0];
            }
            return type;
        }
    }
}
